package com.service.impl;

import com.entity.EIException;
import com.entity.ExamEnrollmentEntity;
import com.entity.StudentEntity;
import com.entity.vo.ExamCardVO;
import com.service.ExamEnrollmentService;
import com.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.Map;
import java.util.List;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.utils.PageUtils;
import com.utils.Query;


import com.dao.ExampaperDao;
import com.entity.ExampaperEntity;
import com.service.ExampaperService;
import com.entity.vo.ExampaperVO;
import com.entity.view.ExampaperView;

import javax.el.ELException;

@Service("exampaperService")
public class ExampaperServiceImpl extends ServiceImpl<ExampaperDao, ExampaperEntity> implements ExampaperService {


    @Autowired
    private ExamEnrollmentService examEnrollmentService;

    @Autowired
    private StudentService studentService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        Page<ExampaperEntity> page = this.selectPage(
                new Query<ExampaperEntity>(params).getPage(),
                new EntityWrapper<ExampaperEntity>()
        );
        return new PageUtils(page);
    }

    @Override
    public PageUtils queryPage(Map<String, Object> params, Wrapper<ExampaperEntity> wrapper) {
        Page<ExampaperView> page = new Query<ExampaperView>(params).getPage();
        page.setRecords(baseMapper.selectListView(page, wrapper));
        PageUtils pageUtil = new PageUtils(page);
        return pageUtil;
    }

    @Override
    public List<ExampaperVO> selectListVO(Wrapper<ExampaperEntity> wrapper) {
        return baseMapper.selectListVO(wrapper);
    }

    @Override
    public ExampaperVO selectVO(Wrapper<ExampaperEntity> wrapper) {
        return baseMapper.selectVO(wrapper);
    }

    @Override
    public List<ExampaperView> selectListView(Wrapper<ExampaperEntity> wrapper) {
        return baseMapper.selectListView(wrapper);
    }

    @Override
    public ExampaperView selectView(Wrapper<ExampaperEntity> wrapper) {
        return baseMapper.selectView(wrapper);
    }


    @Override
    public List<ExamCardVO> listExamCards() {
        // 先更新考试状态
        updateExamStatus();

        // 查询未删除的考试
        EntityWrapper<ExampaperEntity> ew = new EntityWrapper<ExampaperEntity>();
        ew.orderBy("create_time", false);
        return baseMapper.selectList(ew)
                .stream()
                .map(this::convertToVO)
                .collect(Collectors.toList());
    }

    /**
     * 更新所有考试状态
     */
    private void updateExamStatus() {
        LocalDateTime now = LocalDateTime.now();

        EntityWrapper<ExampaperEntity> ew = new EntityWrapper<ExampaperEntity>();
        ew.ne("status", 4);
        List<ExampaperEntity> exams = baseMapper.selectList(ew); // 不包括已结束的考试

        for (ExampaperEntity exam : exams) {
            Integer newStatus = calculateExamStatus(exam, now);
            if (!exam.getStatus().equals(newStatus)) {
                exam.setStatus(newStatus);
                baseMapper.updateById(exam);
            }
        }
    }

    private Integer calculateExamStatus(ExampaperEntity exam, LocalDateTime now) {
        // 已结束
        if (exam.getEndTime() != null && now.isAfter(exam.getEndTime())) {
            return 4;
        }
        // 考试中
        if (exam.getStartTime() != null && now.isAfter(exam.getStartTime())) {
            return 3;
        }
        // 报名结束
        if (exam.getEnrollmentEnd() != null && now.isAfter(exam.getEnrollmentEnd())) {
            return 2;
        }
        // 报名中
        if (exam.getEnrollmentStart() != null && now.isAfter(exam.getEnrollmentStart())) {
            return 1;
        }
        // 未开始
        return 0;
    }

    private ExamCardVO convertToVO(ExampaperEntity exam) {
        ExamCardVO vo = new ExamCardVO();
        vo.setId(exam.getId());
        vo.setName(exam.getName());
        vo.setDescription(exam.getBrief());
        vo.setCoverImage(exam.getCoverImage());
        vo.setStatus(exam.getStatus());

        // 确保状态是最新的
        LocalDateTime now = LocalDateTime.now();
        vo.setStatus(calculateExamStatus(exam, now));

        // 根据不同状态设置不同的展示信息
        switch (exam.getStatus()) {
            case 0: // 未开始
                vo.setEnrollStartTime(exam.getEnrollmentStart().toLocalDate().toString());
                vo.setDuration(exam.getDuration());
                break;

            case 1: // 报名中
                vo.setEnrollRemainDays((int) ChronoUnit.DAYS.between(now, exam.getEnrollmentEnd()));
                //vo.setEnrollCount(exam.getEnrollCount());
                break;

            case 2: // 报名结束
                vo.setExamTime(exam.getStartTime().toString());
                //vo.setEnrollCount(exam.getEnrollCount());
                break;

            case 3: // 考试中
                long remainSeconds = ChronoUnit.SECONDS.between(now, exam.getEndTime());
                long days = remainSeconds / (24 * 3600);
                long hours = (remainSeconds % (24 * 3600)) / 3600;
                long minutes = (remainSeconds % 3600) / 60;
                long seconds = remainSeconds % 60;
                String remainTime = null;
                if (days > 0) {
                    remainTime = String.format("%d天%02d时%02d分", days, hours, minutes);
                } else if (hours > 0) {
                    remainTime = String.format("%02d时%02d分%02d秒", hours, minutes, seconds);
                } else {
                    remainTime = String.format("%02d分%02d秒", minutes, seconds);
                }
                vo.setRemainTime(remainTime);
                //vo.setSubmitCount(exam.getSubmitCount());
                break;

            case 4: // 已结束
                vo.setExamTime(exam.getStartTime().toLocalDate().toString());
                //vo.setSubmitCount(exam.getSubmitCount());
                break;
        }

        return vo;
    }

    /**
     * 考试报名
     * @param examId
     * @param userId
     */
    @Override
    public void enrollExam(Long examId, Long userId) {
        ExampaperEntity exam = baseMapper.selectById(examId);
        if (exam == null) {
            throw new EIException("考试不存在");
        }

        if (exam.getStatus() != 1) {
            throw new EIException("考试不在报名阶段");
        }

        LocalDateTime now = LocalDateTime.now();
        if (now.isBefore(exam.getEnrollmentStart()) || now.isAfter(exam.getEnrollmentEnd())) {
            throw new EIException("不在报名时间范围内");
        }

        // 2. 检查是否已经报名
        EntityWrapper<ExamEnrollmentEntity> ew = new EntityWrapper<ExamEnrollmentEntity>();
        ew.eq("exam_id", examId)
                .eq("student_id", userId)
                .ne("status", 2);

        if (examEnrollmentService.selectCount(ew) > 0) {
            throw new EIException("已经报名过该考试");
        }

        ExampaperEntity exampaperEntity = this.baseMapper.selectById(examId);
        StudentEntity studentEntity = studentService.selectById(userId);
        // 3. 创建报名记录
        ExamEnrollmentEntity enrollment = new ExamEnrollmentEntity();
        enrollment.setExamId(examId);
        enrollment.setExamName(exampaperEntity.getName());
        enrollment.setStudentId(userId);
        enrollment.setName(studentEntity.getName());
        enrollment.setCreateTime(now);
        enrollment.setStatus(0);
        examEnrollmentService.insert(enrollment);

        baseMapper.updateById(exam);
    }

    @Override
    public void submitExam(Long examId, Long userId) {
        ExampaperEntity exam = baseMapper.selectById(examId);
        if (exam == null) {
            throw new EIException("考试不存在");
        }

        if (exam.getStatus() != 3) {
            throw new EIException("考试未在进行中");
        }

        LocalDateTime now = LocalDateTime.now();
        if (now.isAfter(exam.getEndTime())) {
            throw new ELException("考试已结束");
        }

        // 2. 检查是否已报名
        EntityWrapper<ExamEnrollmentEntity> enrollWrapper = new EntityWrapper<ExamEnrollmentEntity>();
        enrollWrapper.eq("exam_id", examId)
                .eq("student_id", userId)
                .eq("status", 0);

        ExamEnrollmentEntity enrollment = examEnrollmentService.selectOne(enrollWrapper);
        if (enrollment == null) {
            throw new ELException("未报名该考试");
        }

        // 3. 检查是否已交卷

        // 7. 更新报名记录状态
        enrollment.setStatus(1);
        examEnrollmentService.updateById(enrollment);

        //exam.setSubmitCount(exam.getSubmitCount() + 1);
        baseMapper.updateById(exam);
    }
}
